{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "GE91qWZkm8ZQ"
      },
      "source": [
        "##### Copyright 2019 The TensorFlow Authors."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "YS3NA-i6nAFC"
      },
      "outputs": [],
      "source": [
        "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n",
        "# you may not use this file except in compliance with the License.\n",
        "# You may obtain a copy of the License at\n",
        "#\n",
        "# https://www.apache.org/licenses/LICENSE-2.0\n",
        "#\n",
        "# Unless required by applicable law or agreed to in writing, software\n",
        "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
        "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
        "# See the License for the specific language governing permissions and\n",
        "# limitations under the License."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "7SN5USFEIIK3"
      },
      "source": [
        "# Embeddings de Palavras"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Aojnnc7sXrab"
      },
      "source": [
        "<table class=\"tfo-notebook-buttons\" align=\"left\">\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://www.tensorflow.org/tutorials/text/word_embeddings\">\n",
        "    <img src=\"https://www.tensorflow.org/images/tf_logo_32px.png\" />\n",
        "    Ver no TensorFlow.org</a>\n",
        "  </td>\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://colab.research.google.com/github/tensorflow/docs-l10n/blob/master/site/pt-br/tutorials/text/word_embeddings.ipynb\">\n",
        "    <img src=\"https://www.tensorflow.org/images/colab_logo_32px.png\" />\n",
        "    Executar no Google Colab</a>\n",
        "  </td>\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://github.com/tensorflow/docs-l10n/blob/master/site/pt-br/tutorials/text/word_embeddings.ipynb\">\n",
        "    <img src=\"https://www.tensorflow.org/images/GitHub-Mark-32px.png\" />\n",
        "    Ver código fonte no GitHub</a>\n",
        "  </td>\n",
        "  <td>\n",
        "    <a href=\"https://storage.googleapis.com/tensorflow_docs/docs-l10n/site/pt-br/tutorials/text/word_embeddings.ipynb\"><img src=\"https://www.tensorflow.org/images/download_logo_32px.png\" />Baixar notebook</a>\n",
        "  </td>\n",
        "</table>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Q6mJg1g3apaz"
      },
      "source": [
        "Este tutorial apresenta embedding de palavras. Ele contém código completo para treinar combinações de palavras do zero em um pequeno conjunto de dados e para visualizá-las usando o [Embedding Projector] (http://projector.tensorflow.org) (mostrado na imagem abaixo).\n",
        "\n",
        "<img src = \"https://github.com/tensorflow/docs/blob/master/site/en/tutorials/text/images/embedding.jpg?raw=1\" alt = \"Captura de tela do projetor de embedding\" width = \"400\" />\n",
        "\n",
        "## Representando texto como números\n",
        "\n",
        "Os modelos de aprendizado de máquina recebem vetores (matrizes de números) como entrada. Ao trabalhar com texto, a primeira coisa que devemos fazer é criar uma estratégia para converter seqüências de caracteres em números (ou \"vetorizar\" o texto) antes de alimentá-lo no modelo. Nesta seção, examinaremos três estratégias para fazê-lo.\n",
        "\n",
        "### Codificações one-hot\n",
        "\n",
        "Como primeira idéia, podemos \"codificar\" cada palavra em nosso vocabulário. Considere a frase \"The cat sat on the mat\". O vocabulário (ou palavras únicas) nesta frase é (cat, mat, on, sat, the). Para representar cada palavra, criaremos um vetor de zeros com comprimento igual ao vocabulário e, em seguida, colocaremos 1 no índice que corresponder à palavra. Essa abordagem é mostrada no diagrama a seguir.\n",
        "\n",
        "<img src = \"https://github.com/tensorflow/docs/blob/master/site/en/tutorials/text/images/one-hot.png?raw=1\" alt = \"Diagrama de codificações únicas\" width =\"400\"/>\n",
        "\n",
        "Para criar um vetor que contenha a codificação da sentença, poderíamos concatenar o vetor one-hot de cada palavra.\n",
        "\n",
        "Ponto-chave: Essa abordagem é ineficiente. Um vetor one-hot é escasso (ou seja, a maioria das indicações é zero). Imagine que temos 10.000 palavras no vocabulário. Para codificar cada palavra, criaríamos um vetor em que 99,99% dos elementos são zero.\n",
        "\n",
        "### Codifique cada palavra com um número único\n",
        "\n",
        "Uma segunda abordagem que podemos tentar é codificar cada palavra usando um número único. Continuando o exemplo acima, poderíamos atribuir 1 a \"cat\", 2 a \"mat\" e assim por diante. Poderíamos então codificar a frase \"The cat sat on the mat\" como um vetor denso como [5, 1, 4, 3, 5, 2]. Esta abordagem é eficiente. Em vez de um vetor esparso, agora temos um denso (onde todos os elementos estão cheios).\n",
        "\n",
        "No entanto, existem duas desvantagens nessa abordagem:\n",
        "\n",
        "* A codificação de número inteiro é arbitrária (não captura nenhuma relação entre palavras).\n",
        "\n",
        "* Uma codificação de número inteiro pode ser desafiadora para um modelo interpretar. Um classificador linear, por exemplo, aprende um único peso para cada recurso. Como não há relação entre a similaridade de duas palavras e a similaridade de suas codificações, essa combinação de peso e característica não tem significado.\n",
        "\n",
        "### Embeddings de palavras\n",
        "\n",
        "O embedding de palavras nos fornece uma maneira de usar uma representação eficiente e densa, na qual palavras semelhantes têm uma codificação semelhante. É importante ressaltar que não precisamos especificar essa codificação manualmente. Um embedding é um vetor denso de valores de ponto flutuante (o comprimento do vetor é um parâmetro que você especifica). Em vez de especificar os valores para o embedding manualmente, eles são parâmetros treináveis ​​(pesos aprendidos pelo modelo durante o treinamento, da mesma maneira que um modelo aprende pesos para uma camada densa). É comum ver combinações de palavras de 8 dimensões (para conjuntos de dados pequenos), com até 1024 dimensões ao trabalhar com conjuntos de dados grandes. Um embedding dimensional mais alto pode capturar relacionamentos refinados entre as palavras, mas exige mais dados para aprender.\n",
        "\n",
        "<img src = \"https://github.com/tensorflow/docs/blob/master/site/en/tutorials/text/images/embedding2.png?raw=1\" alt = \"Diagrama de um Embedding\" width = \"400\"/>\n",
        "\n",
        "Acima está um diagrama para um embedding de uma palavra. Cada palavra é representada como um vetor quadridimensional de valores de ponto flutuante. Outra maneira de pensar em um embedding é como \"tabela de pesquisa\". Depois que esses pesos foram aprendidos, podemos codificar cada palavra procurando o vetor denso a que corresponde na tabela."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "SZUQErGewZxE"
      },
      "source": [
        "## Configuração"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "SIXEk5ON5P7h"
      },
      "outputs": [],
      "source": [
        "from __future__ import absolute_import, division, print_function, unicode_literals\n",
        "\n",
        "try:\n",
        "  # %tensorflow_version only exists in Colab.\n",
        "  !pip install tf-nightly\n",
        "except Exception:\n",
        "  pass\n",
        "import tensorflow as tf"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "RutaI-Tpev3T"
      },
      "outputs": [],
      "source": [
        "from tensorflow import keras\n",
        "from tensorflow.keras import layers\n",
        "\n",
        "import tensorflow_datasets as tfds\n",
        "tfds.disable_progress_bar()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "eqBazMiVQkj1"
      },
      "source": [
        "## Usando a camada Embedding\n",
        "\n",
        "Keras facilita o uso de embedding de palavras. Vamos dar uma olhada na camada [Embedding] (https://www.tensorflow.org/api_docs/python/tf/keras/layers/Embedding).\n",
        "\n",
        "A camada de embedding pode ser entendida como uma tabela de pesquisa que mapeia de índices inteiros (que significam palavras específicas) a vetores densos (seus embeddings). A dimensionalidade (ou largura) do embedding é um parâmetro com o qual você pode experimentar para ver o que funciona bem para o seu problema, da mesma maneira que você experimentaria com o número de neurônios em uma camada Dense.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "-OjxLVrMvWUE"
      },
      "outputs": [],
      "source": [
        "embedding_layer = layers.Embedding(1000, 5)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "2dKKV1L2Rk7e"
      },
      "source": [
        "Quando você cria uma camada de embedding, os pesos para a incorporação são inicializados aleatoriamente (como qualquer outra camada). Durante o treinamento, eles são ajustados gradualmente via retropropagação. Uma vez treinadas, as combinações de palavras aprendidas codificam aproximadamente semelhanças entre as palavras (como foram aprendidas para o problema específico em que seu modelo é treinado).\n",
        "\n",
        "Se você passar um número inteiro para uma camada de embedding, o resultado substituirá cada número inteiro pelo vetor da tabela de embedding:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "0YUjPgP7w0PO"
      },
      "outputs": [],
      "source": [
        "result = embedding_layer(tf.constant([1,2,3]))\n",
        "result.numpy()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "O4PC4QzsxTGx"
      },
      "source": [
        "Para problemas de texto ou sequência, a camada Embedding usa um tensor 2D de números inteiros, de forma `(samples, sequence_length)`, onde cada entrada é uma sequência de números inteiros. Pode incorporar seqüências de comprimentos variáveis. Você pode alimentar a camada de embedding acima dos lotes com as formas `(32, 10)` (lote de 32 sequências de comprimento 10) ou `(64, 15)` (lote de 64 sequências de comprimento 15).\n",
        "\n",
        "O tensor retornado possui mais um eixo que a entrada, os vetores de embedding são alinhados ao longo do novo último eixo. Passe um lote de entrada `(2, 3)` e a saída é `(2, 3, N)`"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "vwSYepRjyRGy"
      },
      "outputs": [],
      "source": [
        "result = embedding_layer(tf.constant([[0,1,2],[3,4,5]]))\n",
        "result.shape"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "WGQp2N92yOyB"
      },
      "source": [
        "Quando recebe um lote de seqüências como entrada, uma camada de embedding retorna um tensor de ponto flutuante 3D, de forma `(amostras, comprimento_de_ sequência, dimensão_de_implantação)`. Para converter dessa sequência de comprimento variável para uma representação fixa, há uma variedade de abordagens padrão. Você pode usar uma camada RNN, Attention ou pooling antes de passá-la para uma camada Dense. Este tutorial usa o pool porque é mais simples. O tutorial [Classificação de texto com um RNN] (text_classification_rnn.ipynb) é um bom próximo passo."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "aGicgV5qT0wh"
      },
      "source": [
        "## Aprendendo embeddings do zero"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "_Bh8B1TUT6mV"
      },
      "source": [
        "Neste tutorial, você treinará um classificador de sentimentos nas críticas de filmes do IMDB. No processo, o modelo aprenderá o embedding do zero. Usaremos para um conjunto de dados pré-processado.\n",
        "\n",
        "Para carregar um conjunto de dados de texto do zero, consulte o [Carregando texto tutorial] (../ load_data / text.ipynb)."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "yg6tyxPtp1TE"
      },
      "outputs": [],
      "source": [
        "(train_data, test_data), info = tfds.load(\n",
        "    'imdb_reviews/subwords8k', \n",
        "    split = (tfds.Split.TRAIN, tfds.Split.TEST), \n",
        "    with_info=True, as_supervised=True)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "jjnBsFXaLVPL"
      },
      "source": [
        "Obtenha o codificador (`tfds.features.text.SubwordTextEncoder`) e dê uma rápida olhada no vocabulário.\n",
        "\n",
        "O `\\_` no vocabulário representa espaços. Observe como o vocabulário inclui palavras inteiras (terminando com `\\_`) e palavras parciais que podem ser usadas para criar palavras maiores"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "MYrsTgxhLBfl"
      },
      "outputs": [],
      "source": [
        "encoder = info.features['text'].encoder\n",
        "encoder.subwords[:20]"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "GwCTfSG63Qth"
      },
      "source": [
        "As críticas de filmes podem ter diferentes comprimentos. Usaremos o método `padded_batch` para padronizar os comprimentos das revisões."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "LwSCxER_2Lef"
      },
      "outputs": [],
      "source": [
        "train_batches = train_data.shuffle(1000).padded_batch(10)\n",
        "test_batches = test_data.shuffle(1000).padded_batch(10)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "dF8ORMt2U9lj"
      },
      "source": [
        "Conforme importado, o texto das revisões é codificado por número inteiro (cada número inteiro representa uma palavra específica ou parte da palavra no vocabulário).\n",
        "\n",
        "Observe os zeros à direita, porque o lote é preenchido no exemplo mais longo."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "Se-phCknsoan"
      },
      "outputs": [],
      "source": [
        "train_batch, train_labels = next(iter(train_batches))\n",
        "train_batch.numpy()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "zI9_wLIiWO8Z"
      },
      "source": [
        "### Crie um modelo simples\n",
        "\n",
        "Usaremos a [Keras Sequential API] (../../guide/keras) para definir nosso modelo. Nesse caso, é um modelo de estilo \"Saco contínuo de palavras\".\n",
        "\n",
        "* Em seguida, a camada Embedding pega o vocabulário codificado por número inteiro e procura o vetor de embedding para cada índice de palavras. Esses vetores são aprendidos à medida que o modelo treina. Os vetores adicionam uma dimensão à matriz de saída. As dimensões resultantes são: `(lote, sequência, incorporação)`.\n",
        "\n",
        "* Em seguida, uma camada GlobalAveragePooling1D retorna um vetor de saída de comprimento fixo para cada exemplo calculando a média sobre a dimensão de sequência. Isso permite que o modelo lide com entradas de comprimento variável, da maneira mais simples possível.\n",
        "\n",
        "* Esse vetor de saída de comprimento fixo é canalizado através de uma camada totalmente conectada (dense) com 16 unidades ocultas.\n",
        "\n",
        "* A última camada está densamente conectada com um único nó de saída. Usando a função de ativação sigmóide, esse valor é um valor flutuante entre 0 e 1, representando uma probabilidade (ou nível de confiança) de que a revisão seja positiva.\n",
        "\n",
        "Cuidado: Este modelo não usa mascaramento; portanto, o preenchimento zero é usado como parte da entrada; portanto, o comprimento do preenchimento pode afetar a saída. Para corrigir isso, consulte o [guia de máscara e preenchimento] (../../guide/keras/masking_and_padding)."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "pHLcFtn5Wsqj"
      },
      "outputs": [],
      "source": [
        "embedding_dim=16\n",
        "\n",
        "model = keras.Sequential([\n",
        "  layers.Embedding(encoder.vocab_size, embedding_dim),\n",
        "  layers.GlobalAveragePooling1D(),\n",
        "  layers.Dense(16, activation='relu'),\n",
        "  layers.Dense(1, activation='sigmoid')\n",
        "])\n",
        "\n",
        "model.summary()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "JjLNgKO7W2fe"
      },
      "source": [
        "### Compile e treine o modelo"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "lCUgdP69Wzix"
      },
      "outputs": [],
      "source": [
        "model.compile(optimizer='adam',\n",
        "              loss='binary_crossentropy',\n",
        "              metrics=['accuracy'])\n",
        "\n",
        "history = model.fit(\n",
        "    train_batches,\n",
        "    epochs=10,\n",
        "    validation_data=test_batches, validation_steps=20)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "LQjpKVYTXU-1"
      },
      "source": [
        "Com essa abordagem, nosso modelo alcança uma acurácia de validação de cerca de 88% (observe que o modelo está adaptado demais (overfitting), a precisão do treinamento é significativamente maior)."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "0D3OTmOT1z1O"
      },
      "outputs": [],
      "source": [
        "import matplotlib.pyplot as plt\n",
        "\n",
        "history_dict = history.history\n",
        "\n",
        "acc = history_dict['accuracy']\n",
        "val_acc = history_dict['val_accuracy']\n",
        "loss = history_dict['loss']\n",
        "val_loss = history_dict['val_loss']\n",
        "\n",
        "epochs = range(1, len(acc) + 1)\n",
        "\n",
        "plt.figure(figsize=(12,9))\n",
        "plt.plot(epochs, loss, 'bo', label='Training loss')\n",
        "plt.plot(epochs, val_loss, 'b', label='Validation loss')\n",
        "plt.title('Training and validation loss')\n",
        "plt.xlabel('Epochs')\n",
        "plt.ylabel('Loss')\n",
        "plt.legend()\n",
        "plt.show()\n",
        "\n",
        "plt.figure(figsize=(12,9))\n",
        "plt.plot(epochs, acc, 'bo', label='Training acc')\n",
        "plt.plot(epochs, val_acc, 'b', label='Validation acc')\n",
        "plt.title('Training and validation accuracy')\n",
        "plt.xlabel('Epochs')\n",
        "plt.ylabel('Accuracy')\n",
        "plt.legend(loc='lower right')\n",
        "plt.ylim((0.5,1))\n",
        "plt.show()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "KCoA6qwqP836"
      },
      "source": [
        "## Recuperar os embeddings aprendidos\n",
        "\n",
        "Em seguida, vamos recuperar o embedding da palavra aprendida durante o treinamento. Esta será uma matriz de forma `(vocab_size, embedding-dimension)`."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "t8WwbsXCXtpa"
      },
      "outputs": [],
      "source": [
        "e = model.layers[0]\n",
        "weights = e.get_weights()[0]\n",
        "print(weights.shape) # formato: (vocab_size, embedding_dim)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "J8MiCA77X8B8"
      },
      "source": [
        "Vamos agora escrever os pesos no disco. Para usar o [Embedding Projector] (http://projector.tensorflow.org), enviaremos dois arquivos em formato separado por tabulação: um arquivo de vetores (contendo a incorporação) e um arquivo de metadados (contendo as palavras)."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "GsjempweP9Lq"
      },
      "outputs": [],
      "source": [
        "import io\n",
        "\n",
        "encoder = info.features['text'].encoder\n",
        "\n",
        "out_v = io.open('vecs.tsv', 'w', encoding='utf-8')\n",
        "out_m = io.open('meta.tsv', 'w', encoding='utf-8')\n",
        "\n",
        "for num, word in enumerate(encoder.subwords):\n",
        "  vec = weights[num+1] # pule o 0, está preenchido.\n",
        "  out_m.write(word + \"\\n\")\n",
        "  out_v.write('\\t'.join([str(x) for x in vec]) + \"\\n\")\n",
        "out_v.close()\n",
        "out_m.close()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "JQyMZWyxYjMr"
      },
      "source": [
        "Se você estiver executando este tutorial em [Colaboratory] (https://colab.research.google.com), poderá usar o seguinte trecho para fazer o download desses arquivos na máquina local (ou usar o navegador de arquivos, * Exibir -> Tabela de conteúdo -> Navegador de arquivos *)."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "-gFbbMmvYvhp"
      },
      "outputs": [],
      "source": [
        "try:\n",
        "  from google.colab import files\n",
        "except ImportError:\n",
        "   pass\n",
        "else:\n",
        "  files.download('vecs.tsv')\n",
        "  files.download('meta.tsv')"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "PXLfFA54Yz-o"
      },
      "source": [
        "## Visualize os embeddings\n",
        "\n",
        "Para visualizar nossos embeddings, nós os carregaremos no projetor de embeddings.\n",
        "\n",
        "Abra o [Embedding Projector] (http://projector.tensorflow.org/) (isso também pode ser executado em uma instância local do TensorBoard).\n",
        "\n",
        "* Clique em \"Carregar dados\".\n",
        "\n",
        "* Carregue os dois arquivos que criamos acima: `vecs.tsv` e` meta.tsv`.\n",
        "\n",
        "Os embeddings que você treinou agora serão exibidas. Você pode procurar por palavras para encontrar os vizinhos mais próximos. Por exemplo, tente pesquisar por \"beautiful\". Você pode ver vizinhos como \"wonderful\".\n",
        "\n",
        "Nota: seus resultados podem ser um pouco diferentes, dependendo de como os pesos foram inicializados aleatoriamente antes de treinar a camada de embedding.\n",
        "\n",
        "Nota: experimentalmente, você poderá produzir combinações mais interpretáveis ​​usando um modelo mais simples. Tente excluir a camada `Dense (16)`, treinar novamente o modelo e visualizar os encaixes novamente.\n",
        "\n",
        "<img src = \"https://github.com/tensorflow/docs/blob/master/site/en/tutorials/text/images/embedding.jpg?raw=1\" alt = \"Captura de tela do projetor de embedding\" width = \"400\" />"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "iS_uMeMw3Xpj"
      },
      "source": [
        "## Próximos passos\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "BSgAZpwF5xF_"
      },
      "source": [
        "Este tutorial mostrou como treinar e visualizar o embedding de palavras do zero em um pequeno conjunto de dados.\n",
        "\n",
        "* Para aprender sobre redes recorrentes, consulte o [Guia Keras RNN] (../../guide/keras/rnn.ipynb).\n",
        "\n",
        "* Para saber mais sobre a classificação de texto (incluindo o fluxo de trabalho geral e se você está curioso para saber quando usar combinações versus codificações únicas), recomendamos esta prática guia de classificação de texto (https://developers.google.com/machine-learning/guides/text-classification/step-2-5)."
      ]
    }
  ],
  "metadata": {
    "accelerator": "GPU",
    "colab": {
      "collapsed_sections": [],
      "name": "word_embeddings.ipynb",
      "toc_visible": true
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}
